import json


class Server:
    def __init__(
        self,
        application_name: str,
        server_port: int,
        server_host: str,
        server_reload: bool,
        server_workers: int,
    ):
        self.application_name = application_name
        self.server_port = server_port
        self.server_host = server_host
        self.server_reload = server_reload
        self.server_workers = server_workers

    def to_dict(self):
        return self.__dict__


class Mysql:
    def __init__(
        self, username: str, password: str, host: str, port: int, database: str
    ):
        self.username = username
        self.password = password
        self.host = host
        self.port = port
        self.database = database

    def to_dict(self):
        return self.__dict__


class Oss:
    def __init__(
        self,
        access_key: str,
        secret_key: str,
        bucket_name: str,
        end_point: str,
        file_dir: str,
    ):
        self.access_key = access_key
        self.secret_key = secret_key
        self.bucket_name = bucket_name
        self.end_point = end_point
        self.file_dir = file_dir

    def to_dict(self):
        return self.__dict__


class Redis:
    def __init__(
        self,
        host: str,
        port: int,
        password: str,
        db: int,
        encoding: str,
        decode_responses: bool,
        retry_on_timeout: bool,
    ):
        self.host = host
        self.port = port
        self.password = password
        self.db = db
        self.encoding = encoding
        self.decode_responses = decode_responses
        self.retry_on_timeout = retry_on_timeout

    def to_dict(self):
        return self.__dict__


class Configs:
    def __init__(
        self,
        server: Server,
        oss: Oss,
        mysql: Mysql,
        redis: Redis,
    ):
        self.server = server
        self.mysql = mysql
        self.oss = oss
        self.redis = redis

    def to_json(self):
        json_data = self.__dict__.copy()
        json_data["server"] = self.server.to_dict()
        json_data["oss"] = self.oss.to_dict()
        json_data["redis"] = self.redis.to_dict()
        json_data["mysql"] = self.mysql.to_dict()
        return json.dumps(json_data, ensure_ascii=False)

    @classmethod
    def from_json(cls, json_str):
        data = json.loads(json_str)
        if "configs" in data:
            json_data = data["configs"]
        else:
            json_data = data
        return cls(
            server=Server(**json_data["server"]),
            oss=Oss(**json_data["oss"]),
            redis=Redis(**json_data["redis"]),
            mysql=Mysql(**json_data["mysql"]),
        )
